[1]:
import numpy as np
%matplotlib inline
import matplotlib.pyplot as plt
plt.rcParams['figure.constrained_layout.use'] = True

import xarray as xr
import dask
print(f'dask: {dask.__version__}')
import dask.array
dask.config.set({'array.chunk-size': '512MiB'})

import extra_data as ed
import extra_geom as eg

import toolbox_scs as tb
import toolbox_scs.detectors as tbdet

tb.__file__
dask: 2022.11.0
[1]:
'/home/lleguy/notebooks/ToolBox/src/toolbox_scs/__init__.py'
[2]:
from dask.distributed import Client
client = Client(n_workers=20)
print(client)
<Client: 'tcp://127.0.0.1:38916' processes=20 threads=80, memory=754.39 GiB>

Load binned data

[3]:
proposal = 70003 #2719
runNB = 4 #224 #179
darkrunNB = 5 #225 #180
path = f'/gpfs/exfel/exp/XMPL/202350/p700003/usr/Shared/processed_runs/'
[4]:
data = xr.open_mfdataset(path + f'r{runNB:04d}/*.h5', parallel=True, join='inner')
[5]:
data
[5]:
<xarray.Dataset>
Dimensions:            (module: 16, sa1_pId: 352, bin_delay: 226, pp: 2,
                        y: 128, x: 512, pulse_slot: 2700)
Coordinates:
  * module             (module) int64 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
  * sa1_pId            (sa1_pId) int64 420 424 428 432 ... 1812 1816 1820 1824
  * bin_delay          (bin_delay) float64 223.8 223.8 223.9 ... 238.8 238.9
  * pp                 (pp) object 'pumped' 'unpumped'
Dimensions without coordinates: y, x, pulse_slot
Data variables:
    DSSC               (pp, bin_delay, module, y, x) float64 dask.array<chunksize=(2, 226, 1, 128, 512), meta=np.ndarray>
    PP800_DelayLine    (module, bin_delay) float64 dask.array<chunksize=(1, 226), meta=np.ndarray>
    bunchPatternTable  (module, bin_delay, pulse_slot) float64 dask.array<chunksize=(1, 226, 2700), meta=np.ndarray>
    SCS_SA1            (module, bin_delay, sa1_pId) float32 dask.array<chunksize=(1, 226, 352), meta=np.ndarray>
    SCS_SA3            (module, pp, bin_delay) float32 dask.array<chunksize=(1, 2, 226), meta=np.ndarray>
    BAM1932S           (module, bin_delay) float32 dask.array<chunksize=(1, 226), meta=np.ndarray>
    delay              (module, bin_delay) float64 dask.array<chunksize=(1, 226), meta=np.ndarray>

Geometry

[6]:
quad_pos = [(-122.81101449,    4.77217391),
           (-125.        , -118.24881159),
           (1.52336232, -119.89306931),
           (3.49344928,    2.90901765)]

#geopath = '/gpfs/exfel/exp/SCS/202002/p002719/scratch/Pre-processing/geometry/dssc_geom_AS_aug20.h5'
geopath = './dssc_geom_AS_aug20.h5'

geom = eg.DSSC_1MGeometry.from_h5_file_and_quad_positions(geopath, quad_pos)

# normalize scattering intensity by XGM
pumped_data = data['DSSC'].sel(pp='pumped')/data['SCS_SA3'].sel(pp='pumped', module=0)
unpumped_data = data['DSSC'].sel(pp='unpumped')/data['SCS_SA3'].sel(pp='unpumped', module=0)

Check beam center with geom2

[7]:
masklist = [
    (4, 1, 0),
    (1, 0, 6),
    (7, 1, 7),
    (12, 1, 1),
    (5, 0, 3),
    (14, 0, 4),
    (7, 1, 3),
    (6, 1, 3),
#    (7, 1, 1),
#    (7, 0, 1)
]
qmask = tbdet.quickmask_DSSC_ASIC(masklist)
[8]:
img = qmask*(pumped_data.mean('bin_delay') - unpumped_data.mean('bin_delay')).values

vmin = np.nanpercentile(img.ravel(), 5)
vmax = np.nanpercentile(img.ravel(), 99.5)
[9]:
from matplotlib.colors import LogNorm
from matplotlib.patches import Circle

geom2 = geom.offset((0.000, -0.0019))

ax = geom2.plot_data(img,
                     colorbar=True, #norm=LogNorm(),
                     vmin=-vmax, vmax=vmax,
                     axis_units='m', figsize=(8,8),
                     cmap='RdBu_r')
ax.add_patch(Circle((0, 0), radius=0.025, fill=False, color='white'))
ax.add_patch(Circle((0, 0), radius=0.035, fill=False, color='white'))
ax.set_xlim([0.04, -0.04])
ax.set_ylim([-0.045, 0.045])
[9]:
(-0.045, 0.045)
_images/DSSC_scattering_time-delay_11_1.png
[10]:
pumped_mean = qmask*pumped_data.mean('bin_delay')
unpumped_mean = qmask*unpumped_data.mean('bin_delay')

image_pumped_mean, _ = geom2.position_modules(pumped_mean)
image_unpumped_mean, _ = geom2.position_modules(unpumped_mean)
[11]:
fig, [ax1, ax2, ax3] = plt.subplots(ncols=3, sharex=True, sharey=True, figsize=(8,3))
fig.suptitle(f'proposal: {proposal} run: {runNB} dark: {darkrunNB}')

cmap='viridis'
v1 = image_pumped_mean
vmin = np.nanpercentile(v1.ravel(), 5)
vmax = np.nanpercentile(v1.ravel(), 99.5)
im1 = geom2.plot_data(pumped_mean, ax=ax1,
           vmin=vmin, vmax=vmax, cmap=cmap,
                axis_units='m',
          aspect=1)
ax1.set_title('pumped')

v1 = image_unpumped_mean
im2 = geom2.plot_data(unpumped_mean, ax=ax2,
           vmin=vmin, vmax=vmax, cmap=cmap,
               axis_units='m')
fig.colorbar(im1.images[0], ax=[ax1, ax2], orientation='horizontal')
ax2.set_title('unpumped')

v1 = (image_pumped_mean - image_unpumped_mean)
vmin = np.nanpercentile(v1.ravel(), 5)
vmax = np.nanpercentile(v1.ravel(), 99.5)
im3 = geom2.plot_data(pumped_mean - unpumped_mean, ax=ax3,
           vmin=-vmax, vmax=vmax, cmap='RdBu_r',
            axis_units='m')
fig.colorbar(im3.images[0], ax=[ax3], orientation='horizontal')

ax3.set_title('pumped-unpumped')
ax3.set_xlim([0.04, -0.04])
ax3.set_ylim([-0.04, 0.04])
[11]:
(-0.04, 0.04)
_images/DSSC_scattering_time-delay_13_1.png

Azimuthal integration

Detector and x-ray settings

[12]:
from pyFAI.azimuthalIntegrator import AzimuthalIntegrator

# Wavelength [m]
E = 852.4   # [eV]
c = 299792458   # [m/s]
h = 4.135667696e-15   # [eV-s]
wavelen = (h*c/E)  # [m]

# Detector position [m]
det_dis = 3.1

ai = AzimuthalIntegrator(detector=geom2.to_pyfai_detector(),
                        dist=det_dis,
                        wavelength=wavelen)
WARNING:silx.opencl.common:Unable to import pyOpenCl. Please install it from: https://pypi.org/project/pyopencl
[13]:
Npt = 900

def azint(data, dummy=False):

    rint_bbox, I_bbox = ai.integrate1d(
        data.reshape(16*128, 512),
        npt=Npt,
        unit='q_nm^-1',
        method='bbox'
    )

    if dummy:
        return rint_bbox, I_bbox
    else:
        return I_bbox

q, I = azint(np.zeros((16, 128, 512)), dummy=True)
[14]:
az_pump = xr.apply_ufunc(azint, # the function to apply
                     qmask*pumped_data.chunk(('auto', -1, -1, -1)), # the data for the function, here only one
                     input_core_dims=[['module', 'y', 'x']], # dimension for each input arguments
                     output_core_dims=[['q']], # dimension for each output
                     #exclude_dims=set(('fit_v',)),  # dimensions allowed to change size. Must be set!
                     vectorize=True,
                     dask="parallelized",
                     output_dtypes=[q.dtype],
                     output_sizes={'q': q.shape[0]},
                    ).compute()

az_unpump = xr.apply_ufunc(azint, # the function to apply
                     qmask*unpumped_data.chunk(('auto', -1, -1, -1)), # the data for the function, here only one
                     input_core_dims=[['module', 'y', 'x']], # dimension for each input arguments
                     output_core_dims=[['q']], # dimension for each output
                     #exclude_dims=set(('fit_v',)),  # dimensions allowed to change size. Must be set!
                     vectorize=True,
                     dask="parallelized",
                     output_dtypes=[q.dtype],
                     output_sizes={'q': q.shape[0]},
                    ).compute()
[15]:
t0 = 229.2
az_pump['q'] = q
az_pump['bin_delay'] = az_pump['bin_delay'] - t0
az_unpump['q'] = q
az_unpump['bin_delay'] = az_unpump['bin_delay'] - t0
[16]:
plt.figure(figsize=(4,3))
plt.plot(az_unpump['q'], az_unpump.mean('bin_delay'), label='unpumped')
plt.plot(az_pump['q'], az_pump.sel({'bin_delay': slice(1., 5.)}).mean('bin_delay'),
         label='pumped (1-5ps)')
plt.ylim([1e-6, None])
plt.semilogy()
plt.legend()
plt.xlabel('q (nm$^{-1}$)')
plt.ylabel('Intensity (arb. units)')
plt.title(f'proposal: {proposal} run: {runNB} dark: {darkrunNB}')
[16]:
Text(0.5, 1.0, 'proposal: 70003 run: 4 dark: 5')
_images/DSSC_scattering_time-delay_20_1.png
[17]:
v = 0.0005
plt.figure(figsize=(4,3))
im = plt.pcolormesh(az_pump['q'], az_pump['bin_delay'],
                    az_pump-az_unpump,
                    vmin=-v, vmax=v, cmap='RdBu_r'
                   )
qlow = 0.035
qhigh = 0.05
plt.axvline(qlow, ls='--', c='k', alpha=0.2)
plt.axvline(qhigh, ls='--', c='k', alpha=0.2)

plt.colorbar(label='intensity (arb. units)')
plt.xlabel('q (nm$^{-1}$)')
plt.ylabel('delay (ps)')
plt.title(f'proposal: {proposal} run: {runNB} dark: {darkrunNB}')
[17]:
Text(0.5, 1.0, 'proposal: 70003 run: 4 dark: 5')
_images/DSSC_scattering_time-delay_21_1.png
[18]:
pump_signal = az_pump.sel({'q': slice(qlow, qhigh)}).mean('q')
unpump_signal = az_unpump.sel({'q': slice(qlow, qhigh)}).mean('q')

pump_signal_pret0 = pump_signal.sel({'bin_delay': slice(-4, -2)}).mean('bin_delay')
unpump_signal_pret0 = unpump_signal.sel({'bin_delay': slice(-4, -2)}).mean('bin_delay')
[19]:
plt.figure(figsize=(4,3))
plt.plot(az_pump['bin_delay'], pump_signal/pump_signal_pret0, label='pumped')
plt.plot(az_unpump['bin_delay'], unpump_signal/unpump_signal_pret0, label='unpumped')
plt.legend()
plt.axvline(0, ls='--', c='k', alpha=0.5)
plt.xlabel('delay (ps)')
plt.ylabel('normalized intensity (arb. units)')
plt.title(f'Run {runNB}')
plt.xlim([-2, 8])
plt.title(f'proposal: {proposal} run: {runNB} dark: {darkrunNB}')
[19]:
Text(0.5, 1.0, 'proposal: 70003 run: 4 dark: 5')
_images/DSSC_scattering_time-delay_23_1.png
[ ]: